package com.leisurexi.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Iterator;

/**
 * Nio 非阻塞式客户端
 *
 * @author: leisurexi
 * @date: 2021-01-05 23:10
 */
public class NoBlockClient {

    public static void main(String[] args) {
        try (
                //  获取通道
                SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("localhost", 8888));
                // 打开本地文件的 channel
                FileChannel fileChannel = FileChannel.open(Paths.get("C:\\Users\\lwx\\Desktop\\goddess\\goddess.jpg"), StandardOpenOption.READ)
        ) {

            // 设置为非阻塞
            socketChannel.configureBlocking(false);
            // 获取选择器
            Selector selector = Selector.open();
            // 将通道注册到 selector 并关注读事件
            socketChannel.register(selector, SelectionKey.OP_READ);

            // 使用 buffer 作为数据载体
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            // 读取数据，发往服务端（这其实是将图片数据写入 buffer 的操作）
            while (fileChannel.read(buffer) != -1) {
                // 切换 buffer 为读模式
                buffer.flip();
                // 发送数据到服务端
                socketChannel.write(buffer);
                // 清空 buffer 准备下一次写入数据
                buffer.clear();
            }

            // 轮询 selector 上准备就绪的事件
            while (selector.select() > 0) {
                Iterator<SelectionKey> keyIterator = selector.selectedKeys().iterator();
                while (keyIterator.hasNext()) {
                    SelectionKey key = keyIterator.next();
                    // 读事件就绪
                    if (key.isReadable()) {
                        // 获取对应的 channel
                        SocketChannel channel = (SocketChannel) key.channel();
                        ByteBuffer respBuffer = ByteBuffer.allocate(1024);
                        // 接收服务端的响应结果
                        int readBytes = channel.read(respBuffer);
                        if (readBytes > 0) {
                            // 切换为读模式
                            respBuffer.flip();
                            System.out.println(new String(respBuffer.array(), 0, readBytes));
                        }
                    }
                    // 删除已经处理过的事件
                    keyIterator.remove();
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
